Android Studio2.0 JNI 开发
前言
在当前Android性能不断提高的情况下,Java语言的一些缺陷逐渐被掩盖起来。什么时候使用NDK呢?
当设计的算法要利用Dalvik虚拟机中的所有处理器资源,而且原生运行较为有利,或者你希望的操作拥有尽可能快的处理速度时,就需要使用NDK。
另一个原因则是方便移植,特别对于OpenGL ES应用程序。
再一个原因就是为安全考虑。
但是Java与原生C语言之间的转换也会增加一些资源开销。
开源C库
- ffmpeg 音视频解码
- opencore 音视频
- opencv 图像处理
准备工作
以MAC OS系统为为例,打开命令行窗口
1.获取ndk存放目录的权限。
chmod a+x android-ndk-r10c-darwin-x86_64.bin
2.解压缩
./android-ndk-r10c-darwin-x86_64.bin
(或直接把ndk文件拖进命令行)
3.配置变量环境
pico .bash_profile
然后进行编辑
export NDK_ROOT=/Volumes/macwork/develop/ndk_r10e
export PATH=${PATH}:$NDK_ROOT
4.更新环境变量配置
source .bash_profile
然后再进入samples/hello-jni
目录,再执行ndk-build
目录就可以编译了
5.进入Android studio,由于项目是用Eclipse写的,请选择Import Project
导入Hello-jni项目,然后File -> Project Structure
配置ndk
若出现NDK integration is deprecated in the current plugin
问题,在 gradle.properties 中配置 android.useDeprecatedNdk=true 即可。as2.0已支持ctrl + 点击
跳转到本地方法的定义c函数,没有定义过的方法也会高亮显示,还能自动导包。还在用eclipse的童鞋,you are drunk!都什么年代了。然后可以运行了。
开动学习啦
1.build.gradle配置,mk文件配置
先看app目录下面的build.gradle文件,需要配置jni模块名:
|
|
实际还有更多可以配置
|
|
2.增加一个sayHello()方法
1.在hello-jni.c 中增加如下代码
|
|
应该注意开头的J
字要大写,随后的为包名类名本地方法名
2.然后在HelloJni.java中写上该方法
|
|
然后就可以调用了。其中使用了闭包来导入了编译好的.so文件
|
|
3.或可以使用javah命令直接生成native c头文件
进入到hello-jni/app/src/main/java 目录,执行
|
|
即可生成头文件。
4.运行时as2.0需要关闭instant-run
的功能,否则会出现.so文件找不到的错误。c文件的编译也不需要我们费心了,as自动会编译好。
3.C调用Java代码
C调用logcat打印日志
- 1.修改build.gradle里ndk节点的内容:
|
|
然后添加以下代码到buildTypes下:
|
|
- 2.引入头文件
#include<android/log.h>
,其中包含__android_log_print()
方法,为方便使用做个宏定义:
|
|
c操作java字符串
c中没有string类型,故须将java字符串转化为c语言的char数组
c操作java数组
|
|
4.c代码调用java代码
1.调用自己的方法。env参数指向java虚拟机环境,jobject指向本对象
|
|
2.当在本对象里调用其它类的方法时,需要创建那个类的对象,方法如下
|
|
3.调用静态方法
|
|
补充知识
java方法签名
java和c的比较
java | byte | short | char | int | float | double | long |
---|---|---|---|---|---|---|---|
占用字节数 | 1 | 2 | 2 | 4 | 4 | 8 | 8 |
c | char | short | long | int | float | double | |
---|---|---|---|---|---|---|---|
占用字节数 | 1 | 2 | 4 | 4 | 4 | 8 |
- java中int float double short类型可以直接用c中相应类型代替
- c中的char可用java中的byte代替
- c中的long可用java中int代替
- java中的long可用c中的long long代替
指针(表示一个地址),指针变量(变量的值为地址)
- *在类型后表示该类型的指针变量,int p=&i; 则p=i;表示p指向的地址里存的值,p为int型的指针变量,p的值为i的地址
- *在变量前表示该地址里存的值,*p = i
- 动态分配内存 *p=(int*)malloc(sizeof(int));
c语言内存:
- .data 常量池
- .code 代码段
- .stack 所有静态分配的内存都放在栈内存中,连续分配
- 堆内存 动态分配的内存都放在堆内存中,不连续分配
函数指针
123int (*pf)(int x,int y);pf = add;pf(x,y);
–
学习中…